package cn.mw.cmdb.service.impl;

import cn.mw.cmdb.entity.InstanceInfoExtend;
import cn.mw.cmdb.entity.PropertyInfo;
import cn.mw.cmdb.entity.cloudWisdom.*;
import cn.mw.cmdb.enums.DatasourceSyncTypeEnum;
import cn.mw.cmdb.enums.OperatorTypeDescEnum;
import cn.mw.cmdb.mongoMapper.CloudWisdomInstanceReportHistoryInfoMapper;
import cn.mw.cmdb.mongoMapper.CloudWisdomReportHistoryInfoMapper;
import cn.mw.cmdb.mongoMapper.CloudWisdomReportRuleInfoMapper;
import cn.mw.cmdb.param.InstanceSearchParam;
import cn.mw.cmdb.service.CloudWisdomReportService;
import cn.mw.cmdb.util.CMDBTool;
import cn.mw.cmdb.view.ViewConvertContext;
import cn.mw.cmdb.view.ViewManager;
import cn.mw.components.mongodb.entity.*;
import cn.mw.components.mongodb.exception.BusinessException;
import cn.mw.components.mongodb.tool.CriteriaWrapper;
import cn.mw.log.client.LogClientSimple;
import cn.mw.log.enums.BusinessLogType;
import cn.mw.log.enums.LogLevel;
import cn.mw.microMonitorCommon.api.common.FinanceReportChannelApiService;
import cn.mw.microMonitorCommon.api.powerjob.PowerJobRequestParam;
import cn.mw.microMonitorCommon.api.powerjob.PowerJobService;
import cn.mw.microMonitorCommon.api.powerjob.PowerJobTimeExpressionParam;
import cn.mw.microMonitorCommon.constant.Constants;
import cn.mw.microMonitorCommon.entity.common.FinanceReportChannelDto;
import cn.mw.microMonitorCommon.enums.FinanceReportLogStatusEnum;
import cn.mw.microMonitorCommon.enums.ReportTypeEnum;
import cn.mw.microMonitorCommon.enums.TimeUnitEnum;
import cn.mw.microMonitorCommon.security.utils.SecurityUtils;
import cn.mw.microMonitorCommon.util.DateUtils;
import cn.mw.microMonitorCommon.util.HttpUtils;
import cn.mw.microMonitorCommon.util.IDModelType;
import cn.mw.microMonitorCommon.util.ModuleIDManager;
import cn.mw.microMonitorCommon.utils.DatabaseUtils;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CloudWisdomReportServiceImpl extends BaseSearchService<CloudWisdomReportRuleInfo> implements CloudWisdomReportService {

    @Autowired
    private MessageSource messageSource;

    @Autowired
    private LogClientSimple logClientSimple;

    @Autowired
    private ModuleIDManager moduleIDManager;

    @Autowired
    private CloudWisdomReportRuleInfoMapper cloudWisdomReportRuleInfoMapper;

    @Autowired
    private ViewManager viewManager;

    @Autowired
    private CloudWisdomReportHistoryInfoMapper cloudWisdomReportHistoryInfoMapper;

    @Autowired
    private CloudWisdomInstanceReportHistoryInfoMapper cloudWisdomInstanceReportHistoryInfoMapper;

    @DubboReference(check = false, mock = "true" ,timeout = 15000)
    private FinanceReportChannelApiService financeReportChannelApiService;

    @DubboReference(check = false ,timeout = 15000)
    private PowerJobService powerJobService;

    @Autowired
    private CmdbServiceManage cmdbServiceManage;

    @Autowired
    private CloudWisdomAsyncReportService cloudWisdomAsyncReportService;

    private static final String QUERY_MODEL_URL = "/api/v1/open/model/list";

    private static final String QUERY_MODEL_PROPERTIES_URL = "/api/v1/open/model/get/";

    private static final String TASK_PROCESSOR = "mwCloudWisdomReportProcessor";

    private static final String STATUS_PROPERTIES_NAME = "resourceStatus";
    private static final String STATUS_PROPERTIES_ON = "启用";
    private static final String STATUS_PROPERTIES_OFF = "停用";

    private static final Integer SYNC_POOL_SIZE = 50;

    @Override
    public Boolean addOrUpdateCloudWisdomReportRule(CloudWisdomReportRuleInfo cloudWisdomReportRuleInfo) throws Exception {
        Query existQuery = new Query(CriteriaWrapper.where(CloudWisdomReportRuleInfo::getChannelId).is(cloudWisdomReportRuleInfo.getChannelId()));
        existQuery.addCriteria(CriteriaWrapper.where(CloudWisdomReportRuleInfo::getRuleName).is(cloudWisdomReportRuleInfo.getRuleName()));
        if (StringUtils.isNotBlank(cloudWisdomReportRuleInfo.getId())) {
            existQuery.addCriteria(CriteriaWrapper.where(CloudWisdomReportRuleInfo::getId).ne(cloudWisdomReportRuleInfo.getId()));
        }
        // 同一个上报通道 规则名称
        CloudWisdomReportRuleInfo existInfo = cloudWisdomReportRuleInfoMapper.findOne(existQuery);
        if (existInfo != null) {
            throw new BusinessException("data-unique-error", new Object[]{cloudWisdomReportRuleInfo.getRuleName()});
        }
        FinanceReportChannelDto financeReportChannelDto = financeReportChannelApiService.getFinanceReportChannelById(cloudWisdomReportRuleInfo.getChannelId());
        if (financeReportChannelDto == null) {
            throw new BusinessException("log-add-cloud-wisdom-report-rule-not-exists", null);
        }
        cloudWisdomReportRuleInfo.setChannelName(financeReportChannelDto.getName());
        cloudWisdomReportRuleInfo.setLastUpdateDate(DateUtils.now());
        if (StringUtils.isBlank(cloudWisdomReportRuleInfo.getId())) {
            // 执行新增
            cloudWisdomReportRuleInfo.setCreateDate(DateUtils.now());
            cloudWisdomReportRuleInfo.setCreator(SecurityUtils.getUser().getNickName());
            cloudWisdomReportRuleInfo.setId(moduleIDManager.getIDStr(IDModelType.Model));

            createAsyncJob(cloudWisdomReportRuleInfo);

            cloudWisdomReportRuleInfoMapper.insert(cloudWisdomReportRuleInfo);

            logClientSimple.addBusinessLog(LogLevel.INFO.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                    messageSource.getMessage("mwCmdb-operation-log", new Object[]{SecurityUtils.getUser().getNickName(), DateUtils.now()
                            , BusinessLogType.CMDB_MANAGE.getCnName(), OperatorTypeDescEnum.add.getCname(),
                            messageSource.getMessage("log-add-cloud-wisdom-report-rule", new Object[]{cloudWisdomReportRuleInfo.getRuleName()}, LocaleContextHolder.getLocale()),
                            Constants.OperationStatus.SUCCESS}, LocaleContextHolder.getLocale()));
        } else {
            cloudWisdomReportRuleInfo.setLastUpdatedBy(SecurityUtils.getUser().getNickName());
            Query query = new Query(CriteriaWrapper.where(CloudWisdomReportRuleInfo::getId).is(cloudWisdomReportRuleInfo.getId()));
            CloudWisdomReportRuleInfo existsInfo = cloudWisdomReportRuleInfoMapper.findOne(query);
            if (existsInfo != null) {
                if (existsInfo.getJobId() != null) {
                    powerJobService.deleteJob(List.of(existsInfo.getJobId()));
                }
                createAsyncJob(cloudWisdomReportRuleInfo);
                Update update = CMDBTool.genMongoUpdate(cloudWisdomReportRuleInfo, null, null);
                CMDBTool.updateFirst(cloudWisdomReportRuleInfoMapper, query, update);
            }

            logClientSimple.addBusinessLog(LogLevel.INFO.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                    messageSource.getMessage("mwCmdb-operation-log", new Object[]{SecurityUtils.getUser().getNickName(), DateUtils.now()
                            , BusinessLogType.CMDB_MANAGE.getCnName(), OperatorTypeDescEnum.update.getCname(),
                            messageSource.getMessage("log-update-cloud-wisdom-report-rule", new Object[]{cloudWisdomReportRuleInfo.getRuleName()}, LocaleContextHolder.getLocale()),
                            Constants.OperationStatus.SUCCESS}, LocaleContextHolder.getLocale()));
        }
        return true;
    }

    private void createAsyncJob(CloudWisdomReportRuleInfo cloudWisdomReportRuleInfo) {
        if (DatasourceSyncTypeEnum.auto.getType().equals(cloudWisdomReportRuleInfo.getSyncMethod())) {
            // 自动同步方式需调powerjob接口创建定时任务
            Long jobId = powerJobService.saveOrUpdateJob(getJobParams(cloudWisdomReportRuleInfo)).getData();
            if (jobId == null) {
                throw new RuntimeException("create async job error!");
            }
            cloudWisdomReportRuleInfo.setJobId(jobId);
        }
    }

    private PowerJobRequestParam getJobParams(CloudWisdomReportRuleInfo cloudWisdomReportRuleInfo) {
        PowerJobRequestParam powerJobRequestParam = new PowerJobRequestParam();
        powerJobRequestParam.setJobName(String.format("%s_%s", cloudWisdomReportRuleInfo.getId(), cloudWisdomReportRuleInfo.getRuleName()));
        powerJobRequestParam.setJobParams(cloudWisdomReportRuleInfo.getId());
        PowerJobTimeExpressionParam powerJobTimeExpressionParam = new PowerJobTimeExpressionParam();
        powerJobTimeExpressionParam.setInterval(calcInterval(cloudWisdomReportRuleInfo.getSyncTime(), cloudWisdomReportRuleInfo.getSyncTimeUnit()));
        powerJobRequestParam.setTimeExpression(JSON.toJSONString(powerJobTimeExpressionParam));
        powerJobRequestParam.setProcessorInfo(TASK_PROCESSOR);
        powerJobRequestParam.setEnable(true);
        return powerJobRequestParam;
    }

    private String calcInterval(Integer syncTime, String syncTimeUnit) {
        TimeUnitEnum timeUnitEnum = TimeUnitEnum.getTimeUnitEnumByCode(syncTimeUnit);
        if (timeUnitEnum == null) {
            throw new RuntimeException("syncTimeUnit is error!");
        }
        switch (timeUnitEnum) {
            case hours -> {
                return String.valueOf(60 * 60 * syncTime);
            }
            case minutes -> {
                return String.valueOf(60 * syncTime);
            }
        }
        return null;
    }

    @Override
    public boolean batchDeleteCloudWisdomReportRules(List<String> ids) throws Exception {

        Query query = new Query(CriteriaWrapper.where(CloudWisdomReportRuleInfo::getId).in(ids));
        List<CloudWisdomReportRuleInfo> existsInfos = cloudWisdomReportRuleInfoMapper.find(query);
        if (CollectionUtils.isNotEmpty(existsInfos)) {
            List<Long> jobIds = existsInfos.stream().map(CloudWisdomReportRuleInfo::getJobId).filter(Objects::nonNull).toList();
            if (CollectionUtils.isNotEmpty(jobIds)) {
                // 删除之前的定时任务重新创建定时任务
                powerJobService.deleteJob(jobIds);
            }
            cloudWisdomReportRuleInfoMapper.remove(new Query(CriteriaWrapper.where(CloudWisdomReportRuleInfo::getId).in(ids)));

            logClientSimple.addBusinessLog(LogLevel.INFO.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                    messageSource.getMessage("mwCmdb-operation-log", new Object[]{SecurityUtils.getUser().getNickName(), DateUtils.now()
                            , BusinessLogType.CMDB_MANAGE.getCnName(), OperatorTypeDescEnum.remove.getCname(),
                            messageSource.getMessage("log-delete-cloud-wisdom-report-rule", new Object[]{existsInfos.stream().map(CloudWisdomReportRuleInfo::getRuleName).toList()}, LocaleContextHolder.getLocale()),
                            Constants.OperationStatus.SUCCESS}, LocaleContextHolder.getLocale()));
        }
        return true;
    }

    @Override
    public Object getCloudWisdomReportRuleByPage(SearchParam param) throws Exception {
        List<FinanceReportChannelDto> financeReportChannelDtoList = financeReportChannelApiService.getAllFinanceReportListByType(ReportTypeEnum.cloudWisdomReport.getType());
        param.addSubCondition(CMDBTool.getFieldName(CloudWisdomReportRuleInfo::getChannelId)
                , new SubCondition(CriteriaOpsType.in.name(), financeReportChannelDtoList.stream().map(FinanceReportChannelDto::getId).toList()));
        Criteria criteria = genCriteria(param);
        // 设置引擎类型名称及引擎名称
        List<CloudWisdomReportRuleInfo> resultList = CMDBTool.selectPageList(cloudWisdomReportRuleInfoMapper, criteria, param);
        ViewConvertContext context = new ViewConvertContext();
        return viewManager.getListViewObject(resultList, CloudWisdomReportRuleInfo.class, param, context);
    }

    @Override
    public CloudWisdomModelPageVo getCloudWisdomModelInfoByPage(Integer channelId, SearchParam param) throws Exception {
        CloudWisdomModelQueryParam modelQueryParam = new CloudWisdomModelQueryParam();
        if (StringUtils.isNotBlank(param.getKeywordValue())) {
            modelQueryParam.setKeyWord(param.getKeywordValue());
        }
        CloudWisdomPageMetaVo cloudWisdomPageMetaVo = new CloudWisdomPageMetaVo();
        cloudWisdomPageMetaVo.setPageNum((int) param.getPage().getCurrent());
        cloudWisdomPageMetaVo.setPageSize((int) param.getPage().getSize());
        modelQueryParam.setPageMeta(cloudWisdomPageMetaVo);
        FinanceReportChannelDto financeReportChannelDto = financeReportChannelApiService.getFinanceReportChannelById(channelId);
        if (financeReportChannelDto != null) {
            Map<String, String> headers = getRequestHeader(financeReportChannelDto);
            log.info("getCloudWisdomModelInfoByPage params:{},headers:{}", JSON.toJSONString(modelQueryParam), JSON.toJSONString(headers));
            String requestUrl = String.format(Locale.ENGLISH, "%s%s", financeReportChannelDto.getServerUrl(), QUERY_MODEL_URL);
            String response = HttpUtils.sendPostRequest(requestUrl, JSON.toJSONString(modelQueryParam), headers);
            log.info("getCloudWisdomModelInfoByPage result:{}", response);
            if (StringUtils.isNotBlank(response)) {
                CloudWisdomServiceResponse cloudWisdomServiceResponse = JSON.parseObject(response, CloudWisdomServiceResponse.class);
                if (cloudWisdomServiceResponse.getData() != null) {
                    return JSON.parseObject(JSON.toJSONString(cloudWisdomServiceResponse.getData()), CloudWisdomModelPageVo.class);
                }
            }
        }
        return null;
    }

    private Map<String, String> getRequestHeader(FinanceReportChannelDto financeReportChannelDto) {
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json");
        headers.put("OperateModel", "HTTP_API");
        headers.put("appName", financeReportChannelDto.getAppName());
        headers.put("appKey", financeReportChannelDto.getUserName());
        headers.put("appSecret", financeReportChannelDto.getAuthToken());
        return headers;
    }

    @Override
    public List<CloudWisdomModelPropertyVo> getModelPropertiesListByModelId(Integer channelId, String modelId) {
        FinanceReportChannelDto financeReportChannelDto = financeReportChannelApiService.getFinanceReportChannelById(channelId);
        List<CloudWisdomModelPropertyVo> resultList = new ArrayList<>();
        String requestUrl = String.format(Locale.ENGLISH, "%s%s%s", financeReportChannelDto.getServerUrl(), QUERY_MODEL_PROPERTIES_URL, modelId);
        String response = HttpUtils.sendGetRequest(requestUrl, getRequestHeader(financeReportChannelDto));
        if (StringUtils.isNotBlank(response)) {
            log.info("getModelPropertiesListByModelId result:{}", response);
            CloudWisdomServiceResponse cloudWisdomServiceResponse = JSON.parseObject(response, CloudWisdomServiceResponse.class);
            CloudWisdomModelPropertyResponseVo cloudWisdomModelPropertyResponseVo = JSON.parseObject(JSON.toJSONString(cloudWisdomServiceResponse.getData()), CloudWisdomModelPropertyResponseVo.class);
            cloudWisdomModelPropertyResponseVo.getContent().forEach(item -> {
                resultList.addAll(item.getProperties());
            });
        }
        return resultList;
    }

    @Override
    public CloudWisdomReportResultVo doReport(List<String> ruleIds) throws Exception {
        CloudWisdomReportResultVo cloudWisdomReportResultVo = new CloudWisdomReportResultVo();
        cloudWisdomReportResultVo.setHistoryIdList(new ArrayList<>());
        // 生成上报历史
        Query query = new Query(CriteriaWrapper.where(CloudWisdomReportRuleInfo::getId).in(ruleIds));
        List<CloudWisdomReportRuleInfo> reportRuleInfoList = cloudWisdomReportRuleInfoMapper.find(query);
        if (CollectionUtils.isNotEmpty(reportRuleInfoList)) {
            for (CloudWisdomReportRuleInfo reportRuleInfo : reportRuleInfoList) {
                // 获取源模型所有实例
                String sourceModelId = reportRuleInfo.getSourceModelId();
                InstanceSearchParam instanceSearchParam = new InstanceSearchParam();
                instanceSearchParam.setModelId(sourceModelId);
                InstanceServiceImpl instanceService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
                List<InstanceInfoExtend> instanceInfoList = instanceService.aggregateList(instanceSearchParam);
                if (CollectionUtils.isNotEmpty(instanceInfoList)) {
                    Integer channelId = reportRuleInfo.getChannelId();
                    FinanceReportChannelDto financeReportChannelDto = financeReportChannelApiService.getFinanceReportChannelById(channelId);
                    if (financeReportChannelDto != null) {
                        CloudWisdomReportHistoryInfo cloudWisdomReportHistoryInfo = new CloudWisdomReportHistoryInfo();
                        cloudWisdomReportHistoryInfo.setSuccessCount(0);
                        cloudWisdomReportHistoryInfo.setFailedCount(0);
                        cloudWisdomReportHistoryInfo.setId(moduleIDManager.getIDStr(IDModelType.Model));
                        cloudWisdomReportHistoryInfo.setRuleId(reportRuleInfo.getId());
                        cloudWisdomReportHistoryInfo.setRuleName(reportRuleInfo.getRuleName());
                        cloudWisdomReportHistoryInfo.setReportDate(DateUtils.now());
                        cloudWisdomReportHistoryInfo.setChannelId(channelId);
                        cloudWisdomReportHistoryInfo.setChannelName(financeReportChannelDto.getName());
                        if (SecurityUtils.getUser() != null) {
                            cloudWisdomReportHistoryInfo.setReportBy(SecurityUtils.getUser().getNickName());
                        }

                        // 查询模型上报历史
                        Query instanceReportQuery = new Query(CriteriaWrapper.where(CloudWisdomInstanceReportHistoryInfo::getRuleId).is(reportRuleInfo.getId())
                                .andOperator(CriteriaWrapper.where(CloudWisdomInstanceReportHistoryInfo::getReportResult).is(true)));
                        List<CloudWisdomInstanceReportHistoryInfo> instanceReportHistoryInfoList = cloudWisdomInstanceReportHistoryInfoMapper.find(instanceReportQuery);

                        Map<String, InstanceInfoExtend> instanceId2VoMap = instanceInfoList.stream().collect(Collectors.toMap(InstanceInfoExtend::getId, item -> item, (o1, o2) -> o1));

                        Map<String, CloudWisdomInstanceReportHistoryInfo> instanceId2HisMap = instanceReportHistoryInfoList.stream().collect(Collectors.toMap(CloudWisdomInstanceReportHistoryInfo::getInstanceId, item -> item, (o1, o2) -> {
                            if (DateUtils.parse(o1.getReportDate()).getTime() > DateUtils.parse(o2.getReportDate()).getTime()) {
                                return o1;
                            }
                            return o2;
                        }));

                        List<CloudWisdomReportParam> reportParamList = new ArrayList<>();

                        CloudWisdomReportParam cloudWisdomReportParam;
                        // 设置上报标识 上报历史没有成功记录的设置为新增 有成功记录的设置为更新 上报历史存在成功记录实例列表不存在的设置为删除
                        for (Map.Entry<String, InstanceInfoExtend> entry : instanceId2VoMap.entrySet()) {
                            cloudWisdomReportParam = new CloudWisdomReportParam();
                            cloudWisdomReportParam.setModelId(reportRuleInfo.getTargetModelId());
                            cloudWisdomReportParam.setInstanceId(entry.getKey());
                            cloudWisdomReportParam.setContent(getContentByMappingRule(entry.getValue(), reportRuleInfo.getPropertyMappingList()));
                            if (cloudWisdomReportParam.getContent().containsKey(DatabaseUtils.getFieldName(CloudWisdomReportParam::getCiName))) {
                                cloudWisdomReportParam.setCiName(cloudWisdomReportParam.getContent().get(DatabaseUtils.getFieldName(CloudWisdomReportParam::getCiName)).toString());
                            }
                            if (!cloudWisdomReportParam.getContent().containsKey(STATUS_PROPERTIES_NAME)) {
                                cloudWisdomReportParam.getContent().put(STATUS_PROPERTIES_NAME, STATUS_PROPERTIES_ON);
                            }
                            cloudWisdomReportParam.setInstanceInfoExtend(instanceId2VoMap.get(entry.getKey()));
                            if (instanceId2HisMap.containsKey(entry.getKey())) {
                                // 通过最后更新时间判断 若上报之后有更新 则重新上报
                                if (entry.getValue().getModificationTime() != null && DateUtils.parse(instanceId2HisMap.get(entry.getKey()).getReportDate()).getTime() < entry.getValue().getModificationTime().getTime()) {
                                    cloudWisdomReportParam.setCiId(instanceId2HisMap.get(entry.getKey()).getRequestId());
                                    cloudWisdomReportParam.setOperateType(OperatorTypeDescEnum.update.getCname());
                                    reportParamList.add(cloudWisdomReportParam);
                                }
                            } else {
                                cloudWisdomReportParam.setOperateType(OperatorTypeDescEnum.add.getCname());
                                reportParamList.add(cloudWisdomReportParam);
                            }
                        }

                        for (Map.Entry<String, CloudWisdomInstanceReportHistoryInfo> entry : instanceId2HisMap.entrySet()) {
                            // 已经上报的实例在实例列表不存在时 标识删除标记
                            if (!instanceId2VoMap.containsKey(entry.getKey()) && !StringUtils.equals(entry.getValue().getOperateType(), OperatorTypeDescEnum.remove.getCname())) {
                                cloudWisdomReportParam = new CloudWisdomReportParam();
                                cloudWisdomReportParam.setInstanceId(entry.getKey());
                                cloudWisdomReportParam.setModelId(reportRuleInfo.getTargetModelId());
                                cloudWisdomReportParam.setContent(entry.getValue().getRequestParam());
                                if (cloudWisdomReportParam.getContent().containsKey(DatabaseUtils.getFieldName(CloudWisdomReportParam::getCiName))) {
                                    cloudWisdomReportParam.setCiName(cloudWisdomReportParam.getContent().get(DatabaseUtils.getFieldName(CloudWisdomReportParam::getCiName)).toString());
                                }
                                cloudWisdomReportParam.setCiId(entry.getValue().getRequestId());
                                cloudWisdomReportParam.getContent().put(STATUS_PROPERTIES_NAME, STATUS_PROPERTIES_OFF);
                                cloudWisdomReportParam.setOperateType(OperatorTypeDescEnum.remove.getCname());
                                // 已经删除的实例根据映射模型设置模型及分组名称
                                InstanceInfoExtend instanceInfoExtend = new InstanceInfoExtend();
                                instanceInfoExtend.setModelName(instanceInfoList.get(0).getModelName());
                                instanceInfoExtend.setModelGroupName(instanceInfoList.get(0).getModelGroupName());
                                if (entry.getValue().getRequestParam() != null) {
                                    instanceInfoExtend.setInstanceName(entry.getValue().getRequestParam().getOrDefault("ciName", "").toString());
                                }
                                cloudWisdomReportParam.setInstanceInfoExtend(instanceInfoExtend);
                                reportParamList.add(cloudWisdomReportParam);
                            }
                        }

                        List<CloudWisdomInstanceReportHistoryInfo> cloudWisdomInstanceReportHistoryInfoList = new ArrayList<>();
                        List<CompletableFuture<CloudWisdomInstanceReportHistoryInfo>> futures = new ArrayList<>();
                        syncReport(reportParamList, futures, cloudWisdomInstanceReportHistoryInfoList, financeReportChannelDto);

                        int successCount = 0;
                        int failedCount = 0;
                        for (CloudWisdomInstanceReportHistoryInfo item : cloudWisdomInstanceReportHistoryInfoList) {
                            if (SecurityUtils.getUser() != null) {
                                item.setReportBy(SecurityUtils.getUser().getNickName());
                            }
                            item.setRuleId(reportRuleInfo.getId());
                            item.setHistoryId(cloudWisdomReportHistoryInfo.getId());
                            if (item.getReportResult()) {
                                successCount++;
                            } else {
                                failedCount++;
                            }
                        }
                        if (CollectionUtils.isNotEmpty(cloudWisdomInstanceReportHistoryInfoList)) {
                            cloudWisdomInstanceReportHistoryInfoMapper.insertAll(cloudWisdomInstanceReportHistoryInfoList);

                            if (successCount > 0) {
                                if (failedCount == 0) {
                                    cloudWisdomReportHistoryInfo.setReportResult(FinanceReportLogStatusEnum.completed.getDesc());
                                } else {
                                    cloudWisdomReportHistoryInfo.setReportResult(FinanceReportLogStatusEnum.partCompleted.getDesc());
                                }
                            } else if (failedCount > 0) {
                                cloudWisdomReportHistoryInfo.setReportResult(FinanceReportLogStatusEnum.failed.getDesc());
                            }
                            cloudWisdomReportHistoryInfo.setSuccessCount(successCount);
                            cloudWisdomReportHistoryInfo.setFailedCount(failedCount);
                            cloudWisdomReportHistoryInfoMapper.insert(cloudWisdomReportHistoryInfo);
                        }
                        cloudWisdomReportResultVo.setSuccessCount(cloudWisdomReportHistoryInfo.getSuccessCount() + cloudWisdomReportResultVo.getSuccessCount());
                        cloudWisdomReportResultVo.setFailedCount(cloudWisdomReportHistoryInfo.getFailedCount() + cloudWisdomReportResultVo.getFailedCount());
                        cloudWisdomReportResultVo.getHistoryIdList().add(cloudWisdomReportHistoryInfo.getId());
                    }
                }
            }
        }
        return cloudWisdomReportResultVo;
    }

    private void syncReport(List<CloudWisdomReportParam> paramList, List<CompletableFuture<CloudWisdomInstanceReportHistoryInfo>> futures,
                            List<CloudWisdomInstanceReportHistoryInfo> cloudWisdomInstanceReportHistoryInfoList, FinanceReportChannelDto financeReportChannelDto) throws Exception {
        for (int i = 0; i < paramList.size(); i++) {
            futures.add(cloudWisdomAsyncReportService.doReport(paramList.get(i), financeReportChannelDto));
            if ((i + 1) % SYNC_POOL_SIZE == 0 || i == paramList.size() - 1) {
                // 等待所有异步任务完成
                CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
                for (CompletableFuture<CloudWisdomInstanceReportHistoryInfo> future : futures) {
                    cloudWisdomInstanceReportHistoryInfoList.add(future.get());
                }
                futures.clear();
            }
        }
    }

    private Map<String, Object> getContentByMappingRule(InstanceInfoExtend instanceInfoExtend, List<CloudWisdomPropertyMappingVo> propertyMappingList) throws Exception {
        Map<String, Object> content = new HashMap<>();
        PropertyInfo sourceProperty;
        CloudWisdomModelPropertyVo targetProperty;
        Object sourceValue;
        for (CloudWisdomPropertyMappingVo cloudWisdomPropertyMappingVo : propertyMappingList) {
            sourceProperty = cloudWisdomPropertyMappingVo.getSourceProperty();
            sourceValue = getSourceValue(sourceProperty, instanceInfoExtend);
            targetProperty = cloudWisdomPropertyMappingVo.getTargetProperty();
            // 根据目标字段的约束条件对源字段进行校验
            if (checkByTargetConstraint(sourceValue, targetProperty)) {
                content.put(targetProperty.getAttrID(), sourceValue);
            }
        }
        return content;
    }

    private boolean checkByTargetConstraint(Object sourceValue, CloudWisdomModelPropertyVo targetProperty) {
        return true;
    }

    private Object getSourceValue(PropertyInfo sourceProperty, InstanceInfoExtend instanceInfoExtend) throws Exception {
        String fieldName = sourceProperty.getId();
        Object fieldValue = getFieldValueByFieldName(instanceInfoExtend, fieldName);
        if (fieldValue == null) {
            fieldValue = instanceInfoExtend.getData().get(fieldName);
        }
        return fieldValue;
    }

    public Object getFieldValueByFieldName(Object object, String fieldName) throws IllegalAccessException {
        Class<?> clazz = object.getClass();
        List<Field> fields = getAllFields(clazz);
        for (Field field : fields) {
            field.setAccessible(true);
            if (field.getName().equals(fieldName)) {
                return field.get(object);
            }
        }
        return null;
    }

    private static List<Field> getAllFields(Class<?> clazz) {
        List<Field> fields = new ArrayList<>(Arrays.asList(clazz.getDeclaredFields()));
        // 获取父类的字段
        if (clazz.getSuperclass() != null) {
            fields.addAll(getAllFields(clazz.getSuperclass()));
        }
        return fields;
    }

    @Override
    public Object getCloudWisdomInstanceReportDetailByPage(SearchParam param) throws Exception {
        param.setSearchClass(CloudWisdomInstanceReportHistoryInfo.class);
        Criteria criteria = genCriteria(param);
        if (StringUtils.isEmpty(param.getSortName())) {
            // 默认按照上报事件倒序排列
            param.setSortName(DatabaseUtils.getFieldName(CloudWisdomInstanceReportHistoryInfo::getReportDate));
            param.setSortOrder("DESC");
        }
        // 设置引擎类型名称及引擎名称
        List<CloudWisdomInstanceReportHistoryInfo> resultList = CMDBTool.selectPageList(cloudWisdomInstanceReportHistoryInfoMapper, criteria, param);
        ViewConvertContext context = new ViewConvertContext();
        return viewManager.getListViewObject(resultList, CloudWisdomInstanceReportHistoryInfo.class, param, context);
    }

    @Override
    public Object getCloudWisdomReportHistoryInfoByPage(SearchParam param) throws Exception {
        param.setSearchClass(CloudWisdomReportHistoryInfo.class);
        param.addSubCondition(CMDBTool.getFieldName(CloudWisdomReportHistoryInfo::getDelFlag)
                , new SubCondition(CriteriaOpsType.is.name(), false));
        Criteria criteria = genCriteria(param);
        if (StringUtils.isEmpty(param.getSortName())) {
            // 默认按照上报事件倒序排列
            param.setSortName(DatabaseUtils.getFieldName(CloudWisdomReportHistoryInfo::getReportDate));
            param.setSortOrder("DESC");
        }
        // 设置引擎类型名称及引擎名称
        List<CloudWisdomReportHistoryInfo> resultList = CMDBTool.selectPageList(cloudWisdomReportHistoryInfoMapper, criteria, param);
        ViewConvertContext context = new ViewConvertContext();
        return viewManager.getListViewObject(resultList, CloudWisdomReportHistoryInfo.class, param, context);
    }

    @Override
    public Map<String, Integer> getCloudWisdomReportHistoryStatusCount(SearchParam param) throws Exception {
        param.setSearchClass(CloudWisdomReportHistoryInfo.class);
        Criteria criteria = genCriteria(param);
        param.setPage(null);
        GroupSearchOperation groupSearchOperation = new GroupSearchOperation();
        String groupName = CMDBTool.getFieldName(CloudWisdomReportHistoryInfo::getReportResult);
        groupSearchOperation.addGroupField(CMDBTool.getFieldName(CloudWisdomReportHistoryInfo::getReportResult), groupName);
        groupSearchOperation.addCalculateField(CMDBTool.getFieldName(CloudWisdomReportHistoryStatusCountInfo::getCount), GroupCalculateMethodEnum.count, groupName);
        param.setGroupSearchOperation(groupSearchOperation);
        List<CloudWisdomReportHistoryStatusCountInfo> result = CMDBTool.aggregateAuthorizedList(CloudWisdomReportHistoryStatusCountInfo.class, cloudWisdomReportHistoryInfoMapper, criteria, param);
        Map<String, Integer> status2CountMap = new LinkedHashMap<>();
        status2CountMap.put(FinanceReportLogStatusEnum.completed.getDesc(), 0);
        status2CountMap.put(FinanceReportLogStatusEnum.partCompleted.getDesc(), 0);
        status2CountMap.put(FinanceReportLogStatusEnum.failed.getDesc(), 0);
        if (CollectionUtils.isNotEmpty(result)) {
            Map<String, Integer> queryMap = result.stream().collect(Collectors.toMap(CloudWisdomReportHistoryStatusCountInfo::getId, CloudWisdomReportHistoryStatusCountInfo::getCount));
            for (Map.Entry<String, Integer> item : queryMap.entrySet()) {
                if (status2CountMap.containsKey(item.getKey())) {
                    status2CountMap.put(item.getKey(), status2CountMap.get(item.getKey()) + item.getValue());
                } else {
                    status2CountMap.put(item.getKey(), item.getValue());
                }
            }
        }
        return status2CountMap;
    }

    @Override
    public boolean batchDeleteCloudWisdomReportHistory(List<String> ids) throws Exception {
        Query query = new Query(CriteriaWrapper.where(CloudWisdomReportHistoryInfo::getId).in(ids));
        CloudWisdomReportHistoryInfo cloudWisdomReportHistoryInfo = new CloudWisdomReportHistoryInfo();
        cloudWisdomReportHistoryInfo.setDelFlag(true);
        Update update = CMDBTool.genMongoUpdate(cloudWisdomReportHistoryInfo, null, null);
        CMDBTool.updateFirst(cloudWisdomReportHistoryInfoMapper, query, update);

        logClientSimple.addBusinessLog(LogLevel.INFO.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                messageSource.getMessage("mwCmdb-operation-log", new Object[]{SecurityUtils.getUser().getNickName(), DateUtils.now()
                        , BusinessLogType.CMDB_MANAGE.getCnName(), OperatorTypeDescEnum.remove.getCname(),
                        messageSource.getMessage("log-delete-cloud-wisdom-report-history", new Object[]{ids}, LocaleContextHolder.getLocale()),
                        Constants.OperationStatus.SUCCESS}, LocaleContextHolder.getLocale()));
        return true;
    }

    @Override
    protected CloudWisdomReportRuleInfo genObject() {
        return new CloudWisdomReportRuleInfo();
    }
}
